home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / madtrb10.arc / HASH.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-12-08  |  30.4 KB  |  658 lines

  1. Program HashTable;
  2.  
  3. { *************************************************************************** }
  4. { *                                                                         * }
  5. { *                     CHAIN BUCKET HASHING PROGRAM                        * }
  6. { *                             Program #3                                  * }
  7. { *                                                                         * }
  8. { *                     Class: CS 367     Section: 4                        * }
  9. { *                         Instructor: Wiegand                             * }
  10. { *                                                                         * }
  11. { *                       Written by Chris Maeder                           * }
  12. { *                Edited and Compiled using Turbo Pascal                   * }
  13. { *                            on an IBM PC                                 * }
  14. { *                                                                         * }
  15. { *   DEFINITION:                                                           * }
  16. { *        A hash table is a data structure that does not require           * }
  17. { *        none if any searching to find a piece of data.  Rather, it       * }
  18. { *        provides an efficient means of readily accessing a piece of      * }
  19. { *        data.                                                            * }
  20. { *                                                                         * }
  21. { *   ALGORITHM:                                                            * }
  22. { *        A hash function is applied to part or all of a given piece of    * }
  23. { *        data ( see Function HashValue ).  From the hash function a key   * }
  24. { *        or hash value is determines which describes where the data       * }
  25. { *        should be placed in the hash table.  If there is already a       * }
  26. { *        piece of data at that particular hash value then a collision     * }
  27. { *        occurs, that is to say two pieces of data hashing to the same    * }
  28. { *        hash value.                                                      * }
  29. { *                                                                         * }
  30. { *        Chain bucket hashing circumnavigates this collision problem      * }
  31. { *        by constructing a linked list tied to each element of the        * }
  32. { *        hash table.  When a collision occurs then the data elements      * }
  33. { *        that have hashed to the same hash value are inserted into the    * }
  34. { *        linked list maintaining their sorted ascending order.  An        * }
  35. { *        example can be seen below:                                       * }
  36. { *                                                                         * }
  37. { *               HASH TABLE                                                * }
  38. { *         (an array of pointers)                                          * }
  39. { *                 _______                                                 * }
  40. { *             0. |  Nil  |                                                * }
  41. { *                |_______|      _______       _______       _______       * }
  42. { *             1. |       |____>|  Data |____>|  Data |____>|  Nil  |      * }
  43. { *                |_______|     |_______|     |_______|     |_______|      * }
  44. { *             2. |  Nil  |                                                * }
  45. { *                |_______|        ^Linked List                            * }
  46. { *                |  Nil  |                                                * }
  47. { *                     ___|                                                * }
  48. { *                                                                         * }
  49. { *                    .                                                    * }
  50. { *                    .                                                    * }
  51. { *                    .                                                    * }
  52. { *                                                                         * }
  53. { *                |_____                                                   * }
  54. { *                |  Nil  |                                                * }
  55. { *                |_______|                                                * }
  56. { *            11. |  Nil  |                                                * }
  57. { *                |_______|                                                * }
  58. { *            12. |  Nil  |                                                * }
  59. { *                |_______|                                                * }
  60. { *                                                                         * }
  61. { *                                                                         * }
  62. { *   PURPOSE:                                                              * }
  63. { *        1. Print program heading.                                        * }
  64. { *        2. Provide a means of storing, maintaining, and retrieving       * }
  65. { *           information about Madison friends/family/business             * }
  66. { *           associates through the use of a hash table.                   * }
  67. { *        3. Use chain hashing to handle collisions.                       * }
  68. { *        4. Maintain each chained linked list in sorted order to          * }
  69. { *           facilitate searching.                                         * }
  70. { *        5. Be able to:                                                   * }
  71. { *           a. Insert a data entry into the data set.                     * }
  72. { *           b. Delete a data entry from the data set.                     * }
  73. { *           c. Search for a data entry in the data set.                   * }
  74. { *                                                                         * }
  75. { *   INPUT/OUTPUT:                                                         * }
  76. { *        1. Print program heading.                                        * }
  77. { *        2. The program reads the data entry out of the data file.        * }
  78. { *           a. Echo print the read file entry.                            * }
  79. { *        3. Pass control to the proper data handling procedure.           * }
  80. { *           a. Insert a data entry into the data set.                     * }
  81. { *              i.   Print a message stating what is about to be done.     * }
  82. { *              ii.  Echo print out entry with labels.                     * }
  83. { *              iii. Reply that the data entry was placed into the data    * }
  84. { *                   set.                                                  * }
  85. { *           b. Delete a data entry from the data set.                     * }
  86. { *              i.   Print a message stating what is about to be done.     * }
  87. { *              ii.  Echo print the file entry with labels.                * }
  88. { *              iii. Reply that the data entry was deleted from the data   * }
  89. { *                   set if found otherwise reply that the data entry      * }
  90. { *                   was not found.                                        * }
  91. { *           c. Search for a data entry in the data set.                   * }
  92. { *              i.   Print a message stating what is about to be done.     * }
  93. { *              ii.  Echo print the file entry with labels.                * }
  94. { *              iii. Print out the contents of the data entry if found     * }
  95. { *                   otherwise reply that the data entry was not found.    * }
  96. { *           d. Print that a bad command was entered if the command        * }
  97. { *              entered is not of the type allowed.                        * }
  98. { *        4. After reading the data file and doing the proper operations   * }
  99. { *           on the data.                                                  * }
  100. { *              i.   Print out the hash table and its contents.            * }
  101. { *              ii.  Halt the program.                                     * }
  102. { *                                                                         * }
  103. { *************************************************************************** }
  104.  
  105. Const
  106.   MAX_TABLE_SIZE=12;                            { maximum size of the hash table+1 }
  107.   MAX_NAME_SIZE=16;                             { maximum size of the name entry }
  108.   MAX_BIRTHDATE_SIZE=5;                         { maximum size of the birthdate entry }
  109.   MAX_ADDRESS_SIZE=25;                          { maximum size of the address entry }
  110.   MAX_FILE_ENTRY_SIZE=55;                       { maximum size of the file entry }
  111.   FILE_NAME='Hash.Fil';
  112.   L_PRINT=False;                                { a boolean used to control the re-direction of the output to the printer }
  113.  
  114. Type
  115.   NameString=String[MAX_NAME_SIZE];             { a string type used to store name entries }
  116.   BirthdateString=String[MAX_BIRTHDATE_SIZE];   { a string type used to store birthdate entries }
  117.   AddressString=String[MAX_ADDRESS_SIZE];       { a string type used to store address entries }
  118.   FileEntryString=String[MAX_FILE_ENTRY_SIZE];
  119.   TextString=String[MAX_FILE_ENTRY_SIZE];
  120.  
  121.   Ptr=^Person;                                  { a pointer which points to the data record type 'Person' }
  122.   Person=                                       { a data record type used to store information }
  123.     Record
  124.       Name:NameString;
  125.       Birthdate:BirthdateString;
  126.       Address:AddressString;
  127.       Next:Ptr;
  128.     End; { Person }
  129.  
  130.   IndexType=1..MAX_TABLE_SIZE;
  131.  
  132. Var
  133.   HashPtrTable:Array[0..MAX_TABLE_SIZE] Of Ptr; { an array of pointers which point to the data record type Person }
  134.   HoldPtr:Integer;                              { a temporary pointer used in re-directing the output from the screen
  135.                                                   to the printer }
  136.  
  137.  
  138.  
  139. Procedure PrintHeading;
  140.  
  141. { This procedure prints a heading for the program. }
  142.  
  143. Begin   { PrintHeading }
  144.   WriteLn;
  145.   WriteLn('CHAIN BUCKET HASHING DEMONSTRATION PROGRAM');
  146.   WriteLn;
  147. End;    { PrintHeading }
  148.  
  149.  
  150.  
  151. Procedure InitHashTable;
  152.  
  153. { This procedure initializes the pointers in the pointer array HashPtrTable to
  154.   Nil. }
  155.  
  156. Var
  157.   Index:IndexType;
  158.  
  159. Begin   { InitHashTable }
  160.   For Index:=0 To MAX_TABLE_SIZE Do
  161.     HashPtrTable[Index]:=Nil;
  162. End;    { InitHashTable }
  163.  
  164.  
  165.  
  166. Procedure RemoveFirstEntryFromString(Var Text:TextString);
  167.  
  168. { This procedure removes the first text entry from the passed text string and
  169.   returns the new truncated text string.  The text entries in the passed text
  170.   string are assumed to be delinated by one space.  See the following
  171.   example.
  172.  
  173.          Passed:    Entry1  Entry2  Entry3
  174.          Returned:  Entry2  Entry3                      }
  175.  
  176. Begin   { RemoveFirstEntryFromString }
  177.   If Pos(' ',Text)<>0 Then
  178.     Text:=Copy(Text,(Pos(' ',Text)+1),(Length(Text)-Pos(' ',Text)));
  179. End;    { RemoveFirstEntryFromString }
  180.  
  181.  
  182.  
  183. Procedure ReturnFirstEntryFromString(Var Text:TextString);
  184.  
  185. { This procedure removes the first text entry from the passed text string and
  186.   returns the first text entry.  The text entries in the passed text string
  187.   are assumed to be delinated by one space.  See the following example.
  188.  
  189.          Passed:    Entry1  Entry2  Entry3
  190.          Returned:  Entry1                              }
  191.  
  192. Begin   { ReturnFirstEntryFromString }
  193.   If Pos(' ',Text)<>0 Then
  194.     Text:=Copy(Text,1,(Pos(' ',Text)-1));
  195. End;    { ReturnFirstEntryFromString }
  196.  
  197.  
  198.  
  199. Function Command(Entry:FileEntryString):FileEntryString;
  200.  
  201. { This function is passed a file entry which contains a command as the first
  202.   entry.  This function picks off the command from the file entry and passes
  203.   the command back. }
  204.  
  205. Begin   { Command }
  206.   ReturnFirstEntryFromString(Entry);
  207.   Command:=Entry;
  208. End;    { Command }
  209.  
  210.  
  211.  
  212. Function NameEntry(FileEntry:FileEntryString):NameString;
  213.  
  214. { This function is passed a file entry which contains a name as the second
  215.   entry.  This function picks off the name from the file entry and passes
  216.   the name back. }
  217.  
  218. Begin   { NameEntry }
  219.   RemoveFirstEntryFromString(FileEntry);
  220.   ReturnFirstEntryFromString(FileEntry);
  221.   NameEntry:=FileEntry;
  222. End;    { NameEntry }
  223.  
  224.  
  225.  
  226. Function BirthdateEntry(FileEntry:FileEntryString):BirthdateString;
  227.  
  228. { This function is passed a file entry which contains a birthdate as the third
  229.   entry.  This function picks off the bithdate from the file entry and passes
  230.   the birthdate back. }
  231.  
  232. Begin   { BirthdateEntry }
  233.   RemoveFirstEntryFromString(FileEntry);
  234.   RemoveFirstEntryFromString(FileEntry);
  235.   ReturnFirstEntryFromString(FileEntry);
  236.   BirthdateEntry:=FileEntry;
  237. End;    { BirthdateEntry }
  238.  
  239.  
  240.  
  241. Function AddressEntry(FileEntry:FileEntryString):AddressString;
  242.  
  243. { This function is passed a file entry which contains a address as the fourth
  244.   entry.  This function picks off the address from the file entry and passes
  245.   the address back. }
  246.  
  247. Begin   { AddressEntry }
  248.   RemoveFirstEntryFromString(FileEntry);
  249.   RemoveFirstEntryFromString(FileEntry);
  250.   RemoveFirstEntryFromString(FileEntry);
  251.   AddressEntry:=FileEntry;
  252. End;    { AddressEntry }
  253.  
  254.  
  255.  
  256. Function HashValue(PersonName:NameString):IndexType;
  257.  
  258. { This function determines a hash table value for the passed PersonName.  This
  259.   function does this by first adding up the ASCII values of all the characters
  260.   in the passed PersonName.  It then determines a hash table value between 0
  261.   and MAX_TABLE_SIZE by applying the Mod function to the accumulated ASCII
  262.   value. }
  263.  
  264. Var
  265.   CharNumber:Integer;
  266.   ASCIIvalue:Integer;
  267.  
  268. Begin   { HashValue }
  269.   ASCIIvalue:=0; { initialize accumulator }
  270.   For CharNumber:=1 To Length(PersonName) Do
  271.     ASCIIvalue:=ASCIIvalue+Ord(Copy(PersonName,CharNumber,1));
  272.   HashValue:=ASCIIvalue Mod (MAX_TABLE_SIZE+1);
  273. End;    { HashValue }
  274.  
  275.  
  276.  
  277. Procedure PrintQueryRecord(PersonDataRecord:Person);
  278.  
  279. { This procedure prints the contents of the passed record that was
  280.   searched for and found. }
  281.  
  282. Begin   { PrintQueryRecord }
  283.   WriteLn;
  284.   WriteLn('Record information about name searched for:');
  285.   With PersonDataRecord Do
  286.     Begin
  287.       WriteLn('   Name      : ',Name);
  288.       WriteLn('   Birthdate : ',Birthdate);
  289.       WriteLn('   Address   : ',Address);
  290.     End; { With PersonDataRecord }
  291. End;    { PrintQueryRecord }
  292.  
  293.  
  294.  
  295. Procedure PrintHashTableContents;
  296.  
  297. { This procedure prints out the hash table and its contents. }
  298.  
  299. Var
  300.   Index:IndexType;
  301.   CurrentPerson:Ptr;                            { a temporary  pointer used in traversing the linked list }
  302.  
  303. Begin   { PrintHashTableContents }
  304.   WriteLn;WriteLn;
  305.   WriteLn;WriteLn;
  306.   WriteLn('          HASH TABLE CONTENTS');
  307.   WriteLn;
  308.   WriteLn('Table Index           Names hashing to this index');
  309.   For Index:=0 To MAX_TABLE_SIZE Do
  310.     Begin
  311.       WriteLn;
  312.       Write('    ',Index);
  313.       If HashPtrTable[Index]=Nil Then
  314.         WriteLn('                  No entries')
  315.       Else
  316.         Begin
  317.           If Index<10 Then
  318.             WriteLn('                  ',HashPtrTable[Index]^.Name)
  319.           Else
  320.             WriteLn('                 ',HashPtrTable[Index]^.Name);
  321.           CurrentPerson:=HashPtrTable[Index];
  322.           While CurrentPerson^.Next<> Nil Do
  323.             Begin
  324.               CurrentPerson:=CurrentPerson^.Next;
  325.               WriteLn('                       ',CurrentPerson^.Name);
  326.             End; { While CurrentPerson^.Next }
  327.         End; { Else }
  328.     End; { For Index }
  329. End;    { PrintHashTableContents }
  330.  
  331.  
  332.  
  333. Procedure InsertRecord(Entry:FileEntryString);
  334.  
  335. { This procedure inserts a data record into one of the hash table's linked
  336.   lists maintaining ascending sorted order according to name. Note that there
  337.   are four special cases for inserting a record into the linked list:
  338.  
  339.         1. No linked list present and thus must start linked list.
  340.         2. Insert entry into front of the existing linked list.
  341.         3. Insert entry into the middle of the existing linked list.
  342.         4. Insert entry at the end of the existing linked list.      }
  343.  
  344. Var
  345.   CurrentPerson:Ptr;                            { a temporary  pointer used in traversing the linked list }
  346.   PreviousPerson:Ptr;                           { a temporary  pointer used in traversing the linked list }
  347.   NewPerson:Ptr;                                { a pointer to record type person whose record stores the new data entry }
  348.   Index:IndexType;
  349.   Done:Boolean;                                 { a boolean used to tell the procedure when it has successfully inserted
  350.                                                   the data record }
  351.  
  352. Begin   { InsertRecord }
  353.   WriteLn;
  354.   WriteLn('Inserting a data entry into the data set.');
  355.   New(NewPerson); {Create a new record to temporarily store the new entry }
  356.   With NewPerson^ Do
  357.     Begin { routine to enter information about new person }
  358.       Name:=NameEntry(Entry);
  359.       Birthdate:=BirthdateEntry(Entry);
  360.       Address:=AddressEntry(Entry);
  361.       Next:=Nil; { set next record pointer to Nil }
  362.       WriteLn('   Name      : ',Name);
  363.       WriteLn('   Birthdate : ',Birthdate);
  364.       WriteLn('   Address   : ',Address);
  365.       Index:=HashValue(Name); { determine hash table index value }
  366.     End; { With NewPerson }
  367.   { Special Case One - Check for the existance of linked list and if not existant, then start one with NewPerson }
  368.   If HashPtrTable[Index]=Nil Then
  369.     HashPtrTable[Index]:=NewPerson { no collision - start new linked list }
  370.   Else
  371.     Begin { collision occured }
  372.       CurrentPerson:=HashPtrTable[Index];
  373.       { Special Case Two - Check if NewPerson has to be inserted at the start of the linked list }
  374.       If CurrentPerson^.Name>NewPerson^.Name Then
  375.         Begin { insert NewPerson at the start of the linked list }
  376.           HashPtrTable[Index]:=NewPerson; { have the hash table pointer point to NewPerson as the start of the linked list }
  377.           NewPerson^.Next:=CurrentPerson; { have NewPerson point to previous head of the list }
  378.         End { If CurrentPerson^.Name }
  379.       Else
  380.         Begin
  381.           PreviousPerson:=CurrentPerson;
  382.           Done:=False;
  383.           While (CurrentPerson^.Next<>Nil) And Not Done Do
  384.             { Special Case Three - Insert entry into the middle of the linked list }
  385.             If (PreviousPerson^.Name<NewPerson^.Name) And (NewPerson^.Name<CurrentPerson^.Name) Then
  386.               Begin { insert NewPerson into the middle of the linked list }
  387.                 PreviousPerson^.Next:=NewPerson; { set previous person pointer to point to NewPerson }
  388.                 NewPerson^.Next:=CurrentPerson;  { set NewPerson to point to current person }
  389.                 Done:=True;
  390.                 PrintHashTableContents;
  391.               End { If CurrentPerson^.Name }
  392.             Else
  393.               Begin { Increment pointers to traverse to next link in linked list }
  394.                 PreviousPerson:=CurrentPerson;
  395.                 CurrentPerson:=CurrentPerson^.Next;
  396.               End; { Else }
  397.           If Not Done Then
  398.             { Special Case Four - Insert entry at end of linked list }
  399.             If (PreviousPerson^.Name<NewPerson^.Name) And (NewPerson^.Name<CurrentPerson^.Name) Then
  400.               Begin { insert NewPerson into the second to last position in linked list }
  401.                 PreviousPerson^.Next:=NewPerson; { set previous person pointer to point to NewPerson }
  402.                 NewPerson^.Next:=CurrentPerson;  { set NewPerson to point to current person }
  403.               End { If (PreviousPerson^.Name }
  404.             Else
  405.               CurrentPerson^.Next:=NewPerson;
  406.         End; { Else }
  407.     End; { Else }
  408.   WriteLn;
  409.   WriteLn('The data entry ',NewPerson^.Name,' was entered into the data set.');
  410. End;    { InsertRecord }
  411.  
  412.  
  413.  
  414. Procedure DeleteRecord(Entry:FileEntryString);
  415.  
  416. { This procedure deletes a particular data record from the hash table's
  417.   linked lists, while maintaining ascending sorted order according
  418.   to name.  Note that there are five special cases for inserting into the
  419.   linked list:
  420.  
  421.         1. No linked list present and thus no prior record entry.
  422.         2. Delete entry from front of the linked list.
  423.         3. Delete entry from the middle of the linked list.
  424.         4. Delete entry from the end of the linked list.
  425.         5. Record entry was not found.
  426.  
  427.   It is important to note that this procedure saves search time by only
  428.   traversing through the linked list until it has reached an entry larger than
  429.   the entry it is looking to delete.  It then prints out that the entry was not
  430.   able to be deleted since it was not found. }
  431.  
  432. Var
  433.   CurrentPerson:Ptr;                            { a temporary  pointer used in traversing the linked list }
  434.   PreviousPerson:Ptr;                           { a temporary  pointer used in traversing the linked list }
  435.   PersonToDelete:NameString;                    { a string to store person name used to find record to delete }
  436.   Index:IndexType;
  437.   Found:Boolean;                                { a boolean used to tell procedure when it has  successfully found and
  438.                                                   deleted a data record }
  439.   Quit:Boolean;                                 { a boolean used to tell the procedure to stop looking for the record
  440.                                                   element due to ascending sorted order of the elements }
  441.  
  442. Begin   { DeleteRecord }
  443.   { Routine to enter name so that proper record will be deleted from data set }
  444.   WriteLn;
  445.   WriteLn('Deleting a data entry from the data set.');
  446.   PersonToDelete:=NameEntry(Entry);
  447.   WriteLn('   Name      : ',PersonToDelete);
  448.   Index:=HashValue(PersonToDelete); { determine hash table index value }
  449.   { Special Case One - Check for the existance of linked list and if not existant then print entry to delete not found }
  450.   If HashPtrTable[Index]=Nil Then
  451.     Begin { no collision-entry not found }
  452.       WriteLn;
  453.       WriteLn('The data entry ',PersonToDelete,' was not found in data set.');
  454.     End { If HashPtrTable[Index] }
  455.   Else
  456.     Begin { collision occured }
  457.       CurrentPerson:=HashPtrTable[Index];
  458.       { Special Case Two - Check if PersonToDelete has to be deleted from the front of the linked list }
  459.       If CurrentPerson^.Name=PersonToDelete Then
  460.         Begin { delete person from the front of the linked list }
  461.           If CurrentPerson^.Next<>Nil Then { determine if there exists a linked list extending beyond first entry }
  462.             HashPtrTable[Index]:=CurrentPerson^.Next
  463.           Else
  464.             HashPtrTable[Index]:=Nil; { reset pointer since linked list is now gone }
  465.           WriteLn;
  466.           WriteLn('The data entry ',PersonToDelete,' was deleted from the data set.');
  467.           Dispose(CurrentPerson); {Delete personRecord }
  468.         End { If CurrentPerson^.Name }
  469.       Else
  470.         Begin
  471.           PreviousPerson:=CurrentPerson;
  472.           Quit:=False;
  473.           Found:=False;
  474.           While(CurrentPerson^.Next<>Nil) And Not Found And Not Quit Do
  475.             Begin
  476.               { Special Case Three - Delete from middle of linked list }
  477.               If PersonToDelete<CurrentPerson^.Name Then
  478.                 Quit:=True;
  479.               If CurrentPerson^.Name=PersonToDelete Then
  480.                 Begin { delete current person from middle of linked list }
  481.                   PreviousPerson^.Next:=CurrentPerson^.Next; { set previous person pointer to point to next person }
  482.                   WriteLn;
  483.                   WriteLn('The data entry ',PersonToDelete,' was deleted from the data set.');
  484.                   Dispose(CurrentPerson); { delete person record }
  485.                   Found:=True;
  486.                 End { If CurrentPerson^.Name }
  487.               Else
  488.                 Begin { increment pointer to traverse to next link of linked list }
  489.                   PreviousPerson:=CurrentPerson;
  490.                   CurrentPerson:=CurrentPerson^.Next;
  491.                 End; { Else }
  492.             End; { While CurrentPerson^.Next }
  493.           If Not Found And (CurrentPerson^.Name=PersonToDelete) Then
  494.             { Special Case Four - Delete name from end of linked list }
  495.             Begin
  496.               PreviousPerson^.Next:=Nil;
  497.               WriteLn;
  498.               WriteLn('The data entry ',PersonToDelete,' was deleted from the data set.');
  499.               Dispose(CurrentPerson);
  500.             End { If Not Found }
  501.           Else
  502.             If Not Found Then
  503.               { Special Case Five - No entry was found }
  504.               Begin
  505.                 WriteLn;
  506.                 WriteLn('The data entry ',PersonToDelete,' was not found in the data set.');
  507.               End; { If Not Found }
  508.         End; { Else }
  509.     End; { Else }
  510. End;    { DeleteRecord }
  511.  
  512.  
  513.  
  514. Procedure SearchForRecord(Entry:FileEntryString);
  515.  
  516. { This procedure searches for a particular data record according to the name
  517.   field from the hash table's linked lists.  It then passes the found record
  518.   to the procedure PrintQueryRecord to be printed.  Note that there are five
  519.   special cases for searching a linked list for a particular entry:
  520.  
  521.         1. No linked list present and thus no prior entry.
  522.         2. Record entry found at front of the linked list.
  523.         3. Record entry found in the middle of the linked list.
  524.         4. Record entry found at the end of the linked list.
  525.         5. Record entry was not found.
  526.  
  527.   It is important to note that this procedure saves search time by only
  528.   traversing through the linked list until it has reached an entry larger than
  529.   the entry it is searching for.  It then prints out that the entry was not
  530.   found. }
  531.  
  532. Var
  533.   CurrentPerson:Ptr;                            { a temporary  pointer used in traversing the linked list }
  534.   QueryPerson:NameString;                       { a string used to temporarily store the name whose record is
  535.                                                   being searched for }
  536.   Index:IndexType;
  537.   Found:Boolean;                                { a boolean used to tell the procedure when it has successfully found and
  538.                                                   printed the queried data record }
  539.   Quit:Boolean;                                 { a boolean used to tell the procedure to stop looking for the record
  540.                                                   element due to ascending sorted order of the elements }
  541.  
  542. Begin   { SearchForRecord }
  543.   { routine to enter name so that proper record will be found in data set }
  544.   WriteLn;
  545.   WriteLn('Searching for a data entry in the data set.');
  546.   QueryPerson:=NameEntry(Entry);
  547.   WriteLn('   Name      : ',QueryPerson);
  548.   Index:=HashValue(QueryPerson); { determine hash table index value }
  549.   { Special Case One - Check for the existance of linked list and if not existant then print entry to find not found }
  550.   If HashPtrTable[Index]=Nil Then
  551.     Begin { no collision-query person not found }
  552.       WriteLn;
  553.       WriteLn('The data entry ',QueryPerson,' was not found in the data set.');
  554.     End { If HashPtrTable[Index] }
  555.   Else
  556.     Begin { collision occured }
  557.       CurrentPerson:=HashPtrTable[Index];
  558.       { Special Case Two - Check if query person is at the front of the linked list }
  559.       If CurrentPerson^.Name=QueryPerson Then
  560.         PrintQueryRecord(CurrentPerson^)
  561.       Else
  562.         Begin
  563.           Quit:=False;
  564.           Found:=False;
  565.           While (CurrentPerson^.Next<>Nil) And Not Found And Not Quit Do
  566.             { Special Case Three - Check if query person in middle of linked list }
  567.             Begin
  568.               If QueryPerson<CurrentPerson^.Name Then
  569.                 Quit:=True;
  570.               If CurrentPerson^.Name=QueryPerson Then
  571.                 Begin { query person found-print data record }
  572.                   PrintQueryRecord(CurrentPerson^);
  573.                   Found:=True;
  574.                 End { If CurrentPerson^.Name }
  575.               Else
  576.                 Begin { increment pointer to traverse to next link of the linked list }
  577.                   CurrentPerson:=CurrentPerson^.Next;
  578.                 End; { Else }
  579.             End; { While CurrentPerson^.Next }
  580.           If Not Found And (CurrentPerson^.Name=QueryPerson) Then
  581.             { Special Case Four - Query name at the end of the linked list }
  582.             PrintQueryRecord(CurrentPerson^)
  583.           Else
  584.             { Special Case Five - No entry was found }
  585.             Begin
  586.               WriteLn;
  587.               WriteLn('The data entry ',QueryPerson,' was not found in the data set');
  588.             End; { Else }
  589.         End; { Else }
  590.     End; { Else }
  591. End;    { SearchForRecord }
  592.  
  593.  
  594.  
  595. Procedure ReadInputFile;
  596.  
  597. { This procedure begins by first reading the entry in the declared file.  The
  598.   file entry is in the form
  599.  
  600.              Command Name Birthdate Address
  601.  
  602.   The procedure then determines the command that is contained in the file
  603.   entry.  Possible commands are:
  604.  
  605.            'I'     Insert a record into the data set
  606.            'D'     Delete a record from the data set
  607.            'S'     Search for a record in data set and print out contents
  608.  
  609.   This procedure then passes control to the specific procedure called.
  610.   If none of the above commands were entered in the file entry, the procedure
  611.   prints an error message stating that a bad command was entered. }
  612.  
  613. Var
  614.   DataFile:Text;                                { Text File }
  615.   FileEntry:FileEntryString;
  616.   CommandEntry:FileEntryString;
  617.  
  618. Begin   { ReadInputFile }
  619.   Assign(DataFile,FILE_NAME);                   { assign to a disk file }
  620.   Reset(DataFile);                              { open the file for reading }
  621.   Repeat                                        { read in the file entries }
  622.     ReadLn(DataFile,FileEntry);
  623.     WriteLn;
  624.     WriteLn;
  625.     WriteLn;
  626.     WriteLn;
  627.     WriteLn('File Entry = ',FileEntry);
  628.     CommandEntry:=Command(FileEntry);
  629.     WriteLn;
  630.     WriteLn('Command = ',CommandEntry);
  631.     Case CommandEntry Of                        { pass control to specific procedure }
  632.       'I' : InsertRecord(FileEntry);
  633.       'D' : DeleteRecord(FileEntry);
  634.       'S' : SearchForRecord(FileEntry);
  635.     Else                                        { improper command encountered }
  636.       WriteLn;
  637.       WriteLn('Bad command was found in the following file entry:');
  638.       WriteLn('   ',FileEntry);
  639.     End; { Case Command(FileEntry) }
  640.   Until Eof(DataFile);
  641.   Close(DataFile);                              { close the disk file }
  642. End;    { ReadInputFile }
  643.  
  644.  
  645.  
  646. Begin   { Main Program }
  647.   HoldPtr:=ConOutPtr;                           { temporarily store current output address }
  648.   If L_PRINT Then
  649.     ConOutPtr:=LstOutPtr;                       { re-direct output to the printer }
  650.   PrintHeading;
  651.   InitHashTable;
  652.   ReadInputFile;
  653.   PrintHashTableContents;
  654.   ConOutPtr:=HoldPtr;                           { reset output device address }
  655. End.    { Main Program }
  656.  
  657.  
  658.